package cmd

import (
	"fmt"
	"github.com/cn-ygf/go-admin/internal/modular/system/service"
	"github.com/cn-ygf/go-admin/internal/router"
	"github.com/cn-ygf/go-admin/pkg/config"
	"github.com/cn-ygf/go-admin/pkg/db"
	"github.com/cn-ygf/go-admin/pkg/log"
	"github.com/cn-ygf/go-admin/pkg/redis"
	"github.com/spf13/cobra"
	"os"
	"os/signal"
	"runtime/debug"
	"syscall"
)

var (
	cmdLog = log.NamedLogger("cmd")
)

var rootCmd = &cobra.Command{
	Use:   "g-admin",
	Short: "go-admin",
	Run: func(cmd *cobra.Command, args []string) {
		// Do Stuff Here
		start()
	},
}

var (
	cfgFile string
)

func init() {
	cobra.OnInitialize(initConfig)
	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file")
}

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func initConfig() {
	if cfgFile == "" {
		fmt.Println("error: config not found")
		fmt.Println("Usage:\n\t./go-admin --config=config.yaml")
		os.Exit(0)
	}
	config.Load(cfgFile)
}

func start() {

	defer func() {
		if r := recover(); r != nil {
			cmdLog.Printf("panic:\n%s", debug.Stack())
			fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
			os.Exit(99)
		}
	}()

	level := log.InfoLevel
	if config.GetBool("server.dev") {
		level = log.DebugLevel
	}
	log.SetLevel(level)

	// 加载redis
	if err := redis.Load(); err != nil {
		cmdLog.Errorln(err)
		os.Exit(1)
	}

	// 加载mysql
	err := db.Load()
	if err != nil {
		cmdLog.Errorln(err)
		os.Exit(1)
	}

	// 加载service
	service.Load()

	// 加载参数缓存
	err = service.ConfigService.Load()
	if err != nil {
		cmdLog.Errorln(err)
		os.Exit(1)
	}

	// 启动管理服务
	// apiServer, err := api.StartListener()
	apiServer, err := router.StartListener()
	if err != nil {
		cmdLog.Printf("[!] Failed to start go-admin server %s", err)
		cmdLog.Errorf("Error starting api server listener %s", err)
		os.Exit(1)
	}

	done := make(chan bool)
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR1, syscall.SIGUSR2)
	go func() {
		<-signals
		cmdLog.Infof("Received SIGTERM, exiting ...")
		apiServer.Cleanup()
		redis.Close()
		done <- true
	}()
	<-done
}
